package com.ewing.core.auth.filter;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.ewing.common.constants.ResponseType;
import com.ewing.common.utils.AjaxJsonpUtils;
import com.ewing.common.utils.BasePraramUtils;
import com.ewing.common.utils.SystemPropertyUtils;
import com.ewing.core.app.action.base.ResponseData;
import com.ewing.core.auth.HttpSessionUtils;
import com.ewing.core.mpsdk.WxPropertyManager;
import com.ewing.core.mpsdk.api.UserAPI;
import com.ewing.core.mpsdk.api.WechatAPIImpl;
import com.ewing.core.redis.RedisException;
import com.ewing.core.redis.RedisManage;
import com.ewing.utils.BizGenerator;
import com.ewing.utils.FileUrlUtil;
import com.ewing.utils.JsonUtils;

/**
 * Ajax请求session检查过滤器，可以配置忽略检查的uri：完全匹配的地址/web/abc/abc，通配符形式/web/fs/**
 * 
 * @author Joeson Chan<chenxuegui1234@163.com>
 * @since 2016年3月7日
 */
public class SessionCheckFilter implements Filter {

	private static Logger logger = Logger.getLogger(SessionCheckFilter.class);

	/**
	 * 忽略检查
	 */
	private static final String ignoreUriList = "ignoreUriList";

	private UserAPI useApi = new WechatAPIImpl();

	private Set<String> ignoreUris = null;

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		ignoreUris = new HashSet<String>();
		String sIgnoreUriList = filterConfig.getInitParameter(ignoreUriList);
		if (sIgnoreUriList == null || sIgnoreUriList.length() == 0) {
			return;
		}
		String[] uris = sIgnoreUriList.split(",");
		for (String uri : uris) {
			ignoreUris.add(uri);
		}
	}

	@SuppressWarnings({ "deprecation", "unchecked" })
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		logger.info("params : " + JsonUtils.toJson(request.getParameterMap()));
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;

		String uri = req.getRequestURI();
		String context = req.getContextPath();
		String requestPath = uri.substring(context.length());

		logger.info("host: " + req.getRemoteHost()); 
		if (ignoreCheck(requestPath)) {
			chain.doFilter(request, resp);
			return;
		}

		String curClientUrl = BasePraramUtils.getClientUrl();
		String cookie = BasePraramUtils.getCookie();
		String server = SystemPropertyUtils.getShopDomain();
		// String nsukey = req.getParameter("nsukey");//
		// nsukey只有微信访问的客户才带有nsukey字段

		logger.info("uri " + uri);

		// 已经登陆过，无登陆，无需校验登陆状态
		if (HttpSessionUtils.isLogined() || !SystemPropertyUtils.needAuth()
				|| ignoreCheck(requestPath)) {
			chain.doFilter(req, resp);
			return;
		}

		try {
			// 如果当前客户正在进行微信验证，则对其他请求不做处理
			cookie = StringUtils.isEmpty(cookie) ? BizGenerator.generateUUID()
					: cookie;
			logger.info("cookie " + cookie);
			// 这里始终避免不了同步问题，如果通个客户端两个请求同时并发过来时候，始终还是会有问题
			RedisManage.getInstance().set(cookie, 1);// 正在登陆 redis 对饮cookie 为1

			HttpSessionUtils.setRedirectUrl(curClientUrl);
			// 重定向到第三方登陆(暂时只有微信，后续可能会接入其他登陆)，登陆之后设置PreSessionUserDetails和SessionUserDetails
			if (isWxBrowser(req)) {

				String url = useApi.getWebAuthorizationCode(
						WxPropertyManager.getAppId(),
						URLEncoder.encode(server
								+ "/module/auth/authing.html?shopId="
								+ BasePraramUtils.getShopId()),
						UserAPI.SCOPE_SNSAPI_USERINFO, cookie);

				// 进行前端的一个重定向 @TODO这里传过去的cookie需要加密以下
				AjaxJsonpUtils.outJson(req, resp, JsonUtils
						.toJson(new ResponseData(true, Collections.EMPTY_LIST,
								url, ResponseType.REDIRECT)));
			} else {// sms登陆
				// 进行前端的一个重定向
				AjaxJsonpUtils.outJson(req, resp, JsonUtils
						.toJson(new ResponseData(true, Collections.EMPTY_LIST,
								FileUrlUtil.concatPath(server,
										"/module/sms/login.html?shopId="
												+ BasePraramUtils.getShopId()),
								ResponseType.REDIRECT)));
			}
			return;
		} catch (RedisException e) {
			logger.error(e.getMessage(), e);
		}

	}

	@Override
	public void destroy() {
	}

	/**
	 * 当前请求是否忽略检查，默认返回false，表示需要检查，实现参考AntPathRequestMatcher
	 * 
	 * @param request
	 * @return
	 */
	private boolean ignoreCheck(String requestPath) {
		logger.info("requestPath : " + requestPath);
		requestPath = requestPath.replace("//", "/");
		boolean result = false;
		for (String ignoreUri : ignoreUris) {
			if (requestPath.matches("/" + ignoreUri + "/[\\w\\W]*"))
				return true;

		}
		return result;
	}

	/**
	 * 是否微信浏览器登陆
	 * 
	 * @param request
	 * @return
	 */
	private static boolean isWxBrowser(HttpServletRequest request) {
		if (null == request
				|| StringUtils.isEmpty(request.getHeader("User-Agent"))) {
			return false;
		}
		String ua = request.getHeader("User-Agent").toLowerCase();
		logger.info("ua : " + ua);
		return ua.indexOf("micromessenger") > 0;
	}

	public static void main(String[] args) {
		System.out.println("//apiwx/getAuthCode.action".matches("/apiwx/[\\w\\W]*"));
	}
}
